package plgnet

import (
	"dgo/MyProj/PrjHttpUtils"
	"dgo/MyProj/PrjHttpWs"
	"dgo/goutils/utils"
	"dgo/plg/plgbase"
	"fmt"
	"gitee.com/ymofen/supervalue"
	"math/rand"
	"sync/atomic"
	"time"
)

type ProjWsCltTestPlug struct {
	online_n int32
	start_n  int32
	stop_n   int32
	plgbase.PlgBase
	test_dura    time.Duration
	url          string
	monitor_send *utils.MonitorSpeedSizeRec
	monitor_recv *utils.MonitorSpeedSizeRec
}

func (this *ProjWsCltTestPlug) startTest(url string, client_n, topic_n, data_n int, dura, sleepms time.Duration) error {
	if len(url) == 0 {
		url = this.url
	}
	if len(url) == 0 {
		return fmt.Errorf("%s", "缺少url")
	}
	this.test_dura = dura
	lst := utils.NewVarList()
	lst.RandVars(topic_n, func(idx int) interface{} {
		return utils.RandHexString(24)
	})

	for i := 0; i < client_n; i++ {
		clt := PrjHttpWs.NewWsHttpClt(this.url, "")
		clt.ConfigMonitor(this.monitor_send, this.monitor_recv)
		atomic.AddInt32(&this.start_n, 1)
		clt.OnConnectedFunc = func(sender *PrjHttpWs.WsHttpClt) {
			atomic.AddInt32(&this.online_n, 1)
		}
		clt.ConfigWsOnDis(func(sender *PrjHttpWs.WsClient) {
			atomic.AddInt32(&this.online_n, -1)
		})
		go clt.Start()
		go func() {
			topic := lst.GetValueCycle(rand.Intn(10000)).(string)
			clt.SubScribleTopic(topic)

			for !clt.GetTerminated() {
				sendTopic := lst.GetValueCycle(rand.Intn(10000)).(string)
				json := wrapper.NewSVObject()
				json.SetKeyValue("text", utils.RandKeyString(data_n))
				json.SetKeyValue("t", time.Now().Unix())
				clt.PublishMessage(sendTopic, json)
				time.Sleep(sleepms)
			}
		}()

		utils.AfterExecute("", dura, func() {
			atomic.AddInt32(&this.stop_n, 1)
			clt.Stop()
		})
	}

	return nil

}

func (this *ProjWsCltTestPlug) OnHttpStatus(rec *PlgHttpRec) (rval interface{}, errcode int, err error) {
	json := wrapper.NewSVObject()
	json.SetKeyValues("send-info", fmt.Sprintf("%s, %s", this.monitor_send.SpeedSize(), this.monitor_send.SpeedIO()),
		"recv-info", fmt.Sprintf("%s, %s", this.monitor_recv.SpeedSize(), this.monitor_recv.SpeedIO()),
		"online-n", this.online_n, "start-n", this.start_n, "stop-n", this.stop_n, "dura", this.test_dura.String())
	PrjHttpUtils.JSON2TableRec(rec.RespW, "", json.AsJSONString(false))
	return
}

/*
*
http://58.49.94.210:6003/plug/test/do?action=1&client-n=1000&sleepms=1000&secs=20
*/
func (this *ProjWsCltTestPlug) OnHttpDo(rec *PlgHttpRec) (rval interface{}, errcode int, err error) {
	action := rec.QryAsInt("action", 0)
	if action == 1 {
		this.startTest(rec.QryAsString("url", ""), rec.QryAsInt("client-n", 100),
			rec.QryAsInt("topic-n", 100), rec.QryAsInt("data-n", 1024), time.Duration(rec.QryAsInt64("secs", 60))*time.Second,
			time.Duration(rec.QryAsInt64("sleepms", 100))*time.Millisecond)

		rec.ResponseJSONValues("code", 0, "msg", "测试开始", "t", utils.NowString())
	} else {
		json := wrapper.NewSVObject()
		json.SetKeyValues("action-1", "请求断线")
		PrjHttpUtils.JSON2TableRec(rec.RespW, "", json.String())
	}
	return
}

func (this *ProjWsCltTestPlug) innerDo(conf *wrapper.SuperValue) error {
	if conf == nil {
		return nil
	}

	return this.startTest(conf.StringByName("url", ""),
		conf.IntByName("client-n", 100), conf.IntByName("topic-n", 100), conf.IntByName("data-n", 1024),
		time.Duration(conf.IntByName("secs", 60))*time.Second,
		time.Duration(conf.IntByName("sleepms", 100))*time.Millisecond)
}

/*
**

	{
	  "id":"test",
	  "type":"net.wsclt.test",
	  "conf":{
	    "do":{"client-n":100, "topic-n":100, "data-n":1024, "secs":60, "sleepms":100},
		"url":"ws://119.96.168.202:3000/ws/cmd/service",
	   }
	}
*/
func (this *ProjWsCltTestPlug) ReloadConf(conf *wrapper.SuperValue) error {

	if this.monitor_send == nil {
		this.monitor_send = utils.NewMonitorSpeedSizeRec()
		this.monitor_recv = utils.NewMonitorSpeedSizeRec()
		utils.Monitor.AddMonitorRec(this.monitor_send, this.monitor_send)
		utils.Monitor.AddMonitorRec(this.monitor_recv, this.monitor_recv)
	}

	conf.CheckStrFunc("url", func(strv string) {
		this.url = strv
	})

	return this.innerDo(conf.ValueByName("do"))
}

func (this *ProjWsCltTestPlug) OnObjectNotify(sender interface{}, notifytype int, data interface{}) (rval interface{}, err error) {
	if notifytype == utils.NOTIFY_TYPE_SETCONF {
		if conf, ok := data.(*wrapper.SuperValue); ok {
			err = this.ReloadConf(conf)
		} else {
			err = fmt.Errorf("非法的JSON配置")
		}
	} else if notifytype == utils.NOTIFY_TYPE_RELEASE {
		this.ReleaseFlag = 1

	}
	return
}

func CreateProjWsCltTestPlugFunc(args ...interface{}) (rval interface{}, err error) {
	obj := &ProjWsCltTestPlug{}
	if len(args) > 0 {
		if str, ok := args[0].(string); ok {
			obj.PlugId = str
		}
	}
	rval = obj
	return
}
